package app;

import java.util.ArrayList;
import java.util.List;

import sets.FuzzySetType1;
import sets.IFuzzySet;
import sets.IntervalFuzzySet1;
import universe.Dense;
import universe.Discrete;
import universe.IUniverseOfDiscourse;
import utils.Point;

import linguistic.Qualifier;
import linguistic.Quantifier;
import linguistic.Summarizer;
import linguistic.Variable;
import memberships.MembershipFunction;
import memberships.Trapezoidal;
import memberships.Triangular;

public final class ObjectContructor {
	
	/**
	 * Method creates Quantifier based on given parameters
	 * @param nameQuantifier
	 * @param typeFuzzySet
	 * @param typeFunction
	 * @param pointsFunction
	 * @param typeUniverse
	 * @param elementsUniverse
	 * @return
	 */
	public static Quantifier createQuantifier(
			String nameQuantifier,
			IFuzzySet.Type typeFuzzySet,
			MembershipFunction.Type typeFunction,
			List<Point> pointsFunction,
			IUniverseOfDiscourse.Type typeUniverse,
			List<Double> elementsUniverse
			) {
		
		// Firstly method needs to create universe of discourse
		IUniverseOfDiscourse universe;
		if (typeUniverse == IUniverseOfDiscourse.Type.DENSE) {
			universe = new Dense();
			((Dense)universe).addInterval(elementsUniverse.get(0), elementsUniverse.get(1));
		} else {
			universe = new Discrete();
			for (Double element : elementsUniverse) {
				((Discrete)universe).addElement(element);
			}
		}
		
		// Then creates membership function
		MembershipFunction membershipFunction = null;
		if (typeFunction == MembershipFunction.Type.TRIANGULAR) {
			membershipFunction = new Triangular();
			((Triangular)membershipFunction).setA(pointsFunction.get(0));
			((Triangular)membershipFunction).setB(pointsFunction.get(1));
			((Triangular)membershipFunction).setC(pointsFunction.get(2));
		} else if (typeFunction == MembershipFunction.Type.TRAPEZOIDAL) {
			membershipFunction = new Trapezoidal();
			((Trapezoidal)membershipFunction).setA(pointsFunction.get(0));
			((Trapezoidal)membershipFunction).setB(pointsFunction.get(1));
			((Trapezoidal)membershipFunction).setC(pointsFunction.get(2));
			((Trapezoidal)membershipFunction).setD(pointsFunction.get(3));
		}

		// Lastly lets create fuzzy set
		IFuzzySet fuzzySet = null;
		if (typeFuzzySet == IFuzzySet.Type.TYPE1) {
			fuzzySet = new FuzzySetType1();
			fuzzySet.setUniverseOfDiscorse(universe);
			fuzzySet.setMembershipFunction(membershipFunction);
		}
		
		// And finally Quantifier
		Quantifier quantifier = new Quantifier();
		quantifier.setName(nameQuantifier);
		quantifier.setSet(fuzzySet);
		
		return quantifier;
	}
	
	public static Qualifier createQualifier(
			String nameQualifier,
			IFuzzySet.Type typeFuzzySet,
			MembershipFunction.Type typeFunction,
			List<Point> pointsFunction,
			IUniverseOfDiscourse.Type typeUniverse,
			List<Double> elementsUniverse) {
		
		// Firstly method needs to create universe of discourse
		IUniverseOfDiscourse universe;
		if (typeUniverse == IUniverseOfDiscourse.Type.DENSE) {
			universe = new Dense();
			((Dense)universe).addInterval(elementsUniverse.get(0), elementsUniverse.get(1));
		} else {
			universe = new Discrete();
			for (Double element : elementsUniverse) {
				((Discrete)universe).addElement(element);
			}
		}
		
		// Then creates membership function
		MembershipFunction membershipFunction = null;
		if (typeFunction == MembershipFunction.Type.TRIANGULAR) {
			membershipFunction = new Triangular();
			((Triangular)membershipFunction).setA(pointsFunction.get(0));
			((Triangular)membershipFunction).setB(pointsFunction.get(1));
			((Triangular)membershipFunction).setC(pointsFunction.get(2));
		} else if (typeFunction == MembershipFunction.Type.TRAPEZOIDAL) {
			membershipFunction = new Trapezoidal();
			((Trapezoidal)membershipFunction).setA(pointsFunction.get(0));
			((Trapezoidal)membershipFunction).setB(pointsFunction.get(1));
			((Trapezoidal)membershipFunction).setC(pointsFunction.get(2));
			((Trapezoidal)membershipFunction).setD(pointsFunction.get(3));
		}

		// Lastly lets create fuzzy set
		IFuzzySet fuzzySet = null;
		if (typeFuzzySet == IFuzzySet.Type.TYPE1) {
			fuzzySet = new FuzzySetType1();
			fuzzySet.setUniverseOfDiscorse(universe);
			fuzzySet.setMembershipFunction(membershipFunction);
		}
		
		Qualifier qualifier = new Qualifier();
		qualifier.setName(nameQualifier);
		qualifier.setFuzzySet(fuzzySet);		
		return qualifier;
	}
	
	public static Summarizer createSummarizer(
			String nameSummarizer,
			IFuzzySet.Type typeFuzzySet,
			MembershipFunction.Type typeFunction,
			List<Point> pointsFunction,
			IUniverseOfDiscourse.Type typeUniverse,
			List<Double> elementsUniverse) {
		
		// Firstly method needs to create universe of discourse
		IUniverseOfDiscourse universe;
		if (typeUniverse == IUniverseOfDiscourse.Type.DENSE) {
			universe = new Dense();
			((Dense)universe).addInterval(elementsUniverse.get(0), elementsUniverse.get(1));
		} else {
			universe = new Discrete();
			for (Double element : elementsUniverse) {
				((Discrete)universe).addElement(element);
			}
		}
		
		// Then creates membership function
		MembershipFunction membershipFunction = null;
		if (typeFunction == MembershipFunction.Type.TRIANGULAR) {
			membershipFunction = new Triangular();
			((Triangular)membershipFunction).setA(pointsFunction.get(0));
			((Triangular)membershipFunction).setB(pointsFunction.get(1));
			((Triangular)membershipFunction).setC(pointsFunction.get(2));
		} else if (typeFunction == MembershipFunction.Type.TRAPEZOIDAL) {
			membershipFunction = new Trapezoidal();
			((Trapezoidal)membershipFunction).setA(pointsFunction.get(0));
			((Trapezoidal)membershipFunction).setB(pointsFunction.get(1));
			((Trapezoidal)membershipFunction).setC(pointsFunction.get(2));
			((Trapezoidal)membershipFunction).setD(pointsFunction.get(3));
		}

		// Lastly lets create fuzzy set
		IFuzzySet fuzzySet = null;
		if (typeFuzzySet == IFuzzySet.Type.TYPE1) {
			fuzzySet = new FuzzySetType1();
			fuzzySet.setUniverseOfDiscorse(universe);
			fuzzySet.setMembershipFunction(membershipFunction);
		}
		
		Summarizer summarizer = new Summarizer();
		summarizer.setName(nameSummarizer);
		summarizer.setFuzzySet(fuzzySet);		
		return summarizer;
	}
	
	public static IFuzzySet createFuzzySet(
			IFuzzySet.Type setType,
			MembershipFunction.Type functionType,
			List<Point> functionPoints,
			IUniverseOfDiscourse.Type universeType,
			List<Double> universeBoundary) {
		
		IFuzzySet set;
		
		if (setType == IFuzzySet.Type.TYPE1) {
			set = new FuzzySetType1();
		} else if (setType == IFuzzySet.Type.INTERVAL) {
			set = new FuzzySetType1();
		} else {
			set = new FuzzySetType1();
		}
		
		IUniverseOfDiscourse universe;
		if (universeType == IUniverseOfDiscourse.Type.DENSE) {
			universe = new Dense();
			((Dense)universe).addInterval(universeBoundary.get(0), universeBoundary.get(1));
		} else {
			universe = new Discrete();
			for (Double element : universeBoundary) {
				((Discrete)universe).addElement(element);
			}
		}
		
		MembershipFunction membershipFunction = null;
		if (functionType == MembershipFunction.Type.TRIANGULAR) {
			membershipFunction = new Triangular();
			((Triangular)membershipFunction).setA(functionPoints.get(0));
			((Triangular)membershipFunction).setB(functionPoints.get(1));
			((Triangular)membershipFunction).setC(functionPoints.get(2));
		} else if (functionType == MembershipFunction.Type.TRAPEZOIDAL) {
			membershipFunction = new Trapezoidal();
			((Trapezoidal)membershipFunction).setA(functionPoints.get(0));
			((Trapezoidal)membershipFunction).setB(functionPoints.get(1));
			((Trapezoidal)membershipFunction).setC(functionPoints.get(2));
			((Trapezoidal)membershipFunction).setD(functionPoints.get(3));
		}
		
		set.setUniverseOfDiscorse(universe);
		set.setMembershipFunction(membershipFunction);
		
		return set;
	}
	
	public static IFuzzySet createIntervalFuzzySet(
			MembershipFunction.Type functionType,
			List<Point> functionPoints,
			IUniverseOfDiscourse.Type universeType,
			List<Double> universeBoundary) {
		
		IUniverseOfDiscourse universe = null;
		if (universeType == IUniverseOfDiscourse.Type.DENSE) {
			universe = new Dense();
			((Dense)universe).addInterval(universeBoundary.get(0), universeBoundary.get(1));
		} else if (universeType == IUniverseOfDiscourse.Type.DISCRETE) {
			universe = new Discrete();
			for (Double element : universeBoundary) {
				((Discrete)universe).addElement(element);
			}
		}
		
		MembershipFunction lowerFunction = null;
		MembershipFunction upperFunction = null;
		if (functionType == MembershipFunction.Type.TRIANGULAR) {
			lowerFunction = new Triangular();
			upperFunction = new Triangular();
			
			((Triangular)lowerFunction).setA(functionPoints.get(0));
			((Triangular)lowerFunction).setB(functionPoints.get(1));
			((Triangular)lowerFunction).setC(functionPoints.get(2));
			
			((Triangular)upperFunction).setA(functionPoints.get(3));
			((Triangular)upperFunction).setB(functionPoints.get(4));
			((Triangular)upperFunction).setC(functionPoints.get(5));
		} else if (functionType == MembershipFunction.Type.TRAPEZOIDAL) {
			lowerFunction = new Trapezoidal();
			upperFunction = new Trapezoidal();
			
			((Trapezoidal)lowerFunction).setA(functionPoints.get(0));
			((Trapezoidal)lowerFunction).setB(functionPoints.get(1));
			((Trapezoidal)lowerFunction).setC(functionPoints.get(2));
			((Trapezoidal)lowerFunction).setD(functionPoints.get(3));
			
			((Trapezoidal)upperFunction).setA(functionPoints.get(4));
			((Trapezoidal)upperFunction).setB(functionPoints.get(5));
			((Trapezoidal)upperFunction).setC(functionPoints.get(6));
			((Trapezoidal)upperFunction).setD(functionPoints.get(7));
		}
		
		IntervalFuzzySet1 set = new IntervalFuzzySet1();
		set.setLowerMembershipFunction(lowerFunction);
		set.setUpperMembershipFunction(upperFunction);
		set.setUniverseOfDiscorse(universe);
		
		return set;
	}
	
	public static Variable createVariable(
			String nameVariable,
			IUniverseOfDiscourse universe,
			List<IFuzzySet> fuzzySets
			) {
		
		Variable linguisticVariable = new Variable();
		linguisticVariable.setName(nameVariable);
		linguisticVariable.setUniverse(universe);
		
		for (IFuzzySet set : fuzzySets) {
			//linguisticVariable.addFuzzySet("FUZZY_NAME", set);
		}
		
		return linguisticVariable;
	}
	
	
	
	// Membership function creator
	public static Triangular createTriangular(double a_x, double a_y, double b_x, double b_y, double c_x, double c_y) {
		Triangular membershipFunction = new Triangular();
		membershipFunction.setA(new Point(a_x, a_y));
		membershipFunction.setB(new Point(b_x, b_y));
		membershipFunction.setC(new Point(c_x, c_y));
		return membershipFunction;
	}
	
	public static Trapezoidal createTrapezoidal(double a_x, double a_y, double b_x, double b_y, double c_x, double c_y, double d_x, double d_y) {
		Trapezoidal membershipFunction = new Trapezoidal();
		membershipFunction.setA(new Point(a_x, a_y));
		membershipFunction.setB(new Point(b_x, b_y));
		membershipFunction.setC(new Point(c_x, c_y));
		membershipFunction.setC(new Point(d_x, d_y));
		return membershipFunction;
	}
	
	public static List<Point> createPoints3(double a_x, double a_y, double b_x, double b_y, double c_x, double c_y) {
		List<Point> functionPoints = new ArrayList<>();
		functionPoints.add(new Point(a_x, a_y));
		functionPoints.add(new Point(b_x, b_y));
		functionPoints.add(new Point(c_x, c_y));
		return functionPoints;
	}
	
	public static List<Point> createPoints4(double a_x, double a_y, double b_x, double b_y, double c_x, double c_y, double d_x, double d_y) {
		List<Point> functionPoints = new ArrayList<>();
		functionPoints.add(new Point(a_x, a_y));
		functionPoints.add(new Point(b_x, b_y));
		functionPoints.add(new Point(c_x, c_y));
		functionPoints.add(new Point(d_x, d_y));
		return functionPoints;
	}
	
	public static List<Double> createDenseUniverseBoundary(double min, double max) {
		List<Double> boundary = new ArrayList<>();
		boundary.add(min);
		boundary.add(max);
		return boundary;
	}
	
	public static List<Double> createDiscreteUniverse(double... args) {
		List<Double> universePoints = new ArrayList<>();
		for (double arg : args) {
			universePoints.add(arg);
		}
		return universePoints;
	}
}
